#include "AReVi/arSystem.h"
#include "AReVi/scheduler.h"
using namespace AReVi;

#include "connector.h"
#include "fifo.h"
#include "event.h"

//------------------------------------------------------------------------------

class Test : public ArObject {
public:
	AR_CLASS(Test)
	AR_CONSTRUCTOR_2(Test, StlString, host, unsigned int, port)

protected:
	ArRef<Connector> _connector;

	void _onEvent(ArRef<Event> evt);

	void _onDisconnect(const Connector::DisconnectEvent & evt);
	ArRef<Activity> _act;
	bool _actBalise(ArRef<Activity> act, double dt);
};

AR_CLASS_NOVOID_DEF(Test, ArObject)

Test::Test(ArCW & arCW, StlString host, unsigned int port) : ArObject(arCW) {
	_connector = ConnectorClient::NEW(host, port);
	_connector->addDisconnectCB(thisRef(), &Test::_onDisconnect);
	_connector->addCallback(thisPtr(), &Test::_onEvent);

	_act = Activity::NEW(1.0);
	_act->setBehavior(thisRef(), &Test::_actBalise);
}

Test::~Test() {

}

void Test::_onDisconnect(const Connector::DisconnectEvent &) {
	ArSystem::leaveSimulation();
}

void Test::	_onEvent(ArRef<Event> evt) {
	cout << "Received event :" << endl;
	cout << "- from : " << evt->getEmitterID() << endl;
	cout << "- type : " << evt->getType() << endl;
	cout << "- data : " << evt->getDataSize() << " bytes" << endl;
}

bool Test::_actBalise(ArRef<Activity>, double) {
	static unsigned int i = 0;
    ArRef<Event> evt = Event::NEW();
    evt->setEmitterID(ArSystem::getHostName());
    evt->setType("I'm a client "+doubleToStr(i++));
    _connector->broadcast(evt);
    return true;
}

//------------------------------------------------------------------------------

ArRef<Test> test;

ArRef<Scheduler> simulationInit(void) {
    ArRef<Scheduler> sched=RealTimeScheduler::NEW(1e-3);
    test = Test::NEW("localhost", 12345);
    return(sched);
}

int main(int argc, char ** argv) {
    ArSystem arevi(argc,argv);
    
    Test::REGISTER_CLASS();
    ConnectorClient::REGISTER_CLASS();
	FIFO::REGISTER_CLASS();
    Event::REGISTER_CLASS();

    ArSystem::simulationLoop(&simulationInit);
    return(0);
}

